package com.hik.rpq.proxy.dynamicProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 使用单例工厂模式创建代理对象
 * @author renpeiqian
 * @date 2021/8/6 9:15
 * @since
 */
public class ProxyFactory {


    /**
     * 饿汉式：在项目启动时就创建对象
     * 线程安全，但会浪费内存资源。
     * @param
     * @return
     */
   // private static  ProxyFactory proxyFactory= new ProxyFactory();

    private static  volatile  ProxyFactory proxyFactory;

    private ProxyFactory(){}

    /**
     * 单例模式 : 不频繁创建对象，在第一次使用时创建，后续使用直接调用
     * 关键点：
     * 1.构造函数私有化
     * 2.提供讲台方法获取对象
     * 3.可采用懒汉式或饿汉式获取
     */
    public static ProxyFactory getInstance(){
        return proxyFactory;
    }

    /**
     * 使用双重检验锁来获取单例对象
     * volatile 禁止指令重排，来保证获取的对象都已经初始化。
     * synchronized 保证同步获取
     * @return com.hik.rpq.proxy.dynamicProxy.ProxyFactory
     */
    public static ProxyFactory getSafeInstance(){
        if (proxyFactory ==null){
            synchronized (ProxyFactory.class){
                if (proxyFactory==null){
                    proxyFactory = new ProxyFactory();
                    return  proxyFactory;
                }
            }
        }
        return proxyFactory;
    }

    /**
     * 使用jdk动态代理生成代理对象
     * @param  o   被代理对象
     * @return java.lang.Object 代理对象
     */
    public  Object getJdkProxy( final Object o){
        //使用动态代理生成代理对象，并对被代理对象方法进行增强。
        return  Proxy.newProxyInstance(o.getClass().getClassLoader(),
                o.getClass().getInterfaces(), new InvocationHandler() {

                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object result = null;
                        System.out.println("中介收取租金3000元");
                        //执行被代理对象原有逻辑
                        result = method.invoke(o, args);
                        System.out.println("方法执行后");
                        return result;
                    }
                });

    }
}
